﻿using System;
using Missbot.Common;
using Missbot.Service;
using MongoDB.Bson.Serialization.Attributes;

namespace Missbot.Core.Cache
{
    /// <summary>
    /// 命令锁服务
    /// </summary>
    public class CmdLockerSvc : ISingleton
    {
        /// <summary>
        /// 尝试锁命令
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="Cmd"></param>
        /// <param name="ExpirySpan"></param>
        /// <returns></returns>
        public bool TryLock(string UserID, string Cmd, TimeSpan ExpirySpan)
        {
            if (CmdLockRecDA.IsLocked(UserID, Cmd))
            {
                return false;
            }

            CmdLockRecDA.Insert(UserID, Cmd, ExpirySpan);
            return true;
        }

        /// <summary>
        /// 释放锁
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="Cmd"></param>
        public void ReleaseLock(string UserID, string Cmd)
        {
            CmdLockRecDA.ReleaseLock(UserID, Cmd);
        }
    }

    /// <summary>
    /// 命令锁记录
    /// </summary>
    public class CmdLockRec : DbBaseEntity
    {
        /// <summary>
        /// 用户ID
        /// </summary>
        public string UserID { get; init; }

        /// <summary>
        /// 命令ID
        /// </summary>
        public string Cmd { get; init; }

        /// <summary>
        /// 过期时间
        /// </summary>
        [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
        public DateTime ExpiryTime { get; set; }
    }

    public static class CmdLockRecDA
    {
        /// <summary>
        /// 是否锁定
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="Cmd"></param>
        /// <returns></returns>
        public static bool IsLocked(string UserID, string Cmd)
        {
            return MongoService<CmdLockRec>.Any(p => p.UserID == UserID && p.Cmd == Cmd);
        }

        /// <summary>
        /// 插入记录
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="Cmd"></param>
        /// <param name="ExpirySpan"></param>
        public static void Insert(string UserID, string Cmd, TimeSpan ExpirySpan)
        {
            MongoService<CmdLockRec>.Insert(new CmdLockRec {UserID = UserID, Cmd = Cmd, ExpiryTime = DateTime.Now.Add(ExpirySpan)});
        }

        /// <summary>
        /// 解锁
        /// </summary>
        /// <param name="UserID"></param>
        /// <param name="Cmd"></param>
        public static void ReleaseLock(string UserID, string Cmd)
        {
            MongoService<CmdLockRec>.DeleteMany(p => p.UserID == UserID && p.Cmd == Cmd);
        }
    }
}